package com.lyf.auth.service.impl;

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;
import java.util.List;

import com.lyf.auth.dataDao.AuthConfigurationDao;
import com.lyf.auth.domain.pojo.JWKInfo;
import com.lyf.auth.domain.pojo.JwksInfo;
import com.lyf.auth.domain.response.GetJWKsResponseBody;
import com.lyf.auth.service.EncryptService;
import com.lyf.auth.utils.UUIDUtil;
import com.lyf.common.exception.ApiException;
import org.apache.commons.codec.digest.DigestUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

@Service
public class EncryptServiceImpl implements EncryptService {
   private static final Logger logger = LoggerFactory.getLogger(EncryptServiceImpl.class);
   private static List<JWKInfo> jwkInfosCache = null;
   private static Long jwkInfosExpireTime = 0L;
   @Autowired
   private AuthConfigurationDao authConfigurationDao;
   @Value("${module-conf.public-key}")
   private String publicKey;
   @Value("${module-conf.private-key}")
   private String privateKey;

   private String encrypt(String key, long times, long num) {
      byte[] k = key.getBytes();
      byte[] t = getBytesByLong(times);
      byte[] n = getBytesByLong(num);
      byte[] np = new byte[k.length + t.length + n.length];
      int i = 0;

      int j;
      for(j = 0; j < k.length; ++i) {
         np[i] = k[j];
         ++j;
      }

      for(j = 0; j < t.length; ++i) {
         np[i] = t[j];
         ++j;
      }

      for(j = 0; j < n.length; ++i) {
         np[i] = n[j];
         ++j;
      }

      String sha1 = DigestUtils.sha1Hex(np);
      return sha1;
   }

   private byte[] getBytesByLong(long data) {
      byte[] bytes = new byte[]{(byte)((int)(data & 255L)), (byte)((int)(data >> 8 & 255L)), (byte)((int)(data >> 16 & 255L)), (byte)((int)(data >> 24 & 255L)), (byte)((int)(data >> 32 & 255L)), (byte)((int)(data >> 40 & 255L)), (byte)((int)(data >> 48 & 255L)), (byte)((int)(data >> 56 & 255L))};
      return bytes;
   }
   @Override
   public RSAPublicKey loadPublicKeyFromConf()  {
      return loadPublicKeyFromString(publicKey);
   }
   @Override
   public RSAPrivateKey loadPrivateKeyFromConf()  {
      try {
         byte[] buffer = Base64.getDecoder().decode(privateKey);
         PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(buffer);
         KeyFactory keyFactory = KeyFactory.getInstance("RSA");
         return (RSAPrivateKey)keyFactory.generatePrivate(keySpec);
      } catch (NoSuchAlgorithmException var4) {
         throw new ApiException("无此算法");
      } catch (InvalidKeySpecException var5) {
         throw new ApiException("私钥非法");
      } catch (NullPointerException var6) {
         throw new ApiException("私钥数据为空");
      }
   }
   @Override
   public RSAPublicKey loadPublicKeyFromString(String publicKeyStr)  {
      try {
         byte[] buffer = Base64.getDecoder().decode(publicKeyStr);
         X509EncodedKeySpec keySpec = new X509EncodedKeySpec(buffer);
         KeyFactory keyFactory = KeyFactory.getInstance("RSA");
         return (RSAPublicKey)keyFactory.generatePublic(keySpec);
      } catch (NoSuchAlgorithmException var5) {
         throw new ApiException("无此算法");
      } catch (InvalidKeySpecException var6) {
         throw new ApiException("公钥非法");
      } catch (NullPointerException var7) {
         throw new ApiException("公钥数据为空");
      }
   }
   @Override
   public void genKeyPair() {
      Object var1 = null;

      try {
         KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
         keyPairGenerator.initialize(1024);
         KeyPair keyPair = keyPairGenerator.generateKeyPair();
         RSAPublicKey publicKey = (RSAPublicKey)keyPair.getPublic();
         RSAPrivateKey privateKey = (RSAPrivateKey)keyPair.getPrivate();
         String publicKeyString = Base64.getEncoder().encodeToString(publicKey.getEncoded());
         String privateKeyString = Base64.getEncoder().encodeToString(privateKey.getEncoded());
         FileWriter pubfw = new FileWriter(".\\publicKey.keystore");
         FileWriter prifw = new FileWriter(".\\privateKey.keystore");
         BufferedWriter pubbw = new BufferedWriter(pubfw);
         BufferedWriter pribw = new BufferedWriter(prifw);
         pubbw.write(publicKeyString);
         pribw.write(privateKeyString);
         pubbw.flush();
         pubbw.close();
         pubfw.close();
         pribw.flush();
         pribw.close();
         prifw.close();
      } catch (Exception var12) {
         logger.error("gen ras key error:" + var12);
      }

   }
   @Override
   public GetJWKsResponseBody getJWKs()  {
      GetJWKsResponseBody getJWKsResponseBody = new GetJWKsResponseBody();
      JwksInfo jwks = authConfigurationDao.getJwk();
      if (jwks != null) {
         getJWKsResponseBody.setKeys(jwks.getJwks());
      }

      return getJWKsResponseBody;
   }
   @Override
   public void addJwk(String publicKeyStr) {
      RSAPublicKey rsaPublicKey = loadPublicKeyFromString(publicKeyStr);
      String n = Base64.getEncoder().encodeToString(rsaPublicKey.getModulus().toByteArray());
      String e = Base64.getEncoder().encodeToString(rsaPublicKey.getPublicExponent().toByteArray());
      JWKInfo jwkInfo = new JWKInfo();
      jwkInfo.setN(n);
      jwkInfo.setE(e);
      jwkInfo.setAlg("RS256");
      jwkInfo.setKid(Base64.getEncoder().encodeToString(UUIDUtil.getLowerCaseUUID().getBytes()));
      jwkInfo.setKty("RSA");
      jwkInfo.setUse("sig");
      jwkInfo.setPublicKey(publicKeyStr);
      authConfigurationDao.addJwk(jwkInfo);
   }
}
